שאלה מאוד נפוצה שעולה היא איך לחשב כמה זמן נשאר עד תאריך מסוים, או כמה זמן עבר מאז. php מציעה כלים נוחים לעבודה עם תאריכים, באיחוד בגרסאות האחרונות שלה php > 5.3 באמצעות מחלקת ה-DateTime.
בגרסאות הישנות יותר נצטרך להעביר כל תאריך לשניות
ולחסר את הזמן אחד מהשני באופן ידני. למזלנו עכשיו הכל הרבה יותר פשוט.
מחלקת DateTime
המחלקה dateTime מייצגת נקודת זמן כלשהי (למשל היום) ומכילה מטודות (פונקציות) שונות שניתן לעשות עם אותה יחידת זמן, כמו: חיבור, חיסור, הדפסה באופנים שונים וכו'.
בעזרת הקוד הבא ניצור אובייקט מסוג datetime ונראה מה אפשר לעשות איתו:
$date = new DateTime();
echo $date->format('התאריך d/m/Y, השעה: H:i:s');
echo $date->format('התאריך d/m/Y, השעה: H:i:s');
נוצר לנו אובייקט זמן עם התאריך והשעה הנוכחית. אפשר להדפיס אותו בתבנית מסוימת, לפי רצוננו. האותיות מסמנות את חלקי התאריך והזמן כפי שמפורט בטבלה הזו.
יצירת אובייקט datetime של נקודת זמן שונה מ"עכשיו":
בעבודה עם תאריכים נצטרך להשתמש לא רק בתאריך הנוכחי, אלה מדי פעם גם בתארים עברו או תאריכים עתידיים לבוא. ליצור אובייקט זמן של תאריך אחר אפשר באחת הצורות הבאות:
$datePast = DateTime::createFromFormat('d/m/Y', '06/03/2012');
$past = new DateTime('yesterday');
$past = new DateTime('tomorrow');
$past = new DateTime('+5 days');
$past = new DateTime('-7 years');
$past = new DateTime('+1 week');
$past = new DateTime('yesterday');
$past = new DateTime('tomorrow');
$past = new DateTime('+5 days');
$past = new DateTime('-7 years');
$past = new DateTime('+1 week');
המטודה createFromFormat מנסה לפענח את המחרוזת לפי התבנית שנומר לה.
הבנאי של DateTime יודע לקבל גם טקסט ולפענח אותו לתאריך.
ניצור באופן הזה תאריך בעתיד (למשל 06/03/2012)
ועכשיו ברשותנו שני תאריכים שנוכל לחשב את מרווח הזמן ביניהם.
המחלקה DateInterval
DateInterval היא מחלקה שמייצגת מרווח (הפרש) זמן כלשהו. הפרש זמן יהיה מורכב משנים, חודשים, ימים, שעות, דקות ושניות. חיסור של שני תאריכים אחד מהשני ייצרו אובייקט מסוג dateinterval שיכיל את הפרש הזמנים בין התאריכים:
$now = DateTime::createFromFormat('d/m/Y H:i', '28/04/2011 21:15');
$independence_day = DateTime::createFromFormat('d/m/Y H:i', '15/05/2011 18:00');
$interval = $now->diff($independence_day);
print_r($interval);
$independence_day = DateTime::createFromFormat('d/m/Y H:i', '15/05/2011 18:00');
$interval = $now->diff($independence_day);
print_r($interval);
לצורך העניין כרגע מעכשיו (21:15 28/04/2011)
עד יום העצמאות ( 18:00 15/05/2011) נשאר:
DateInterval Object ( [y] => 0 [m] => 0 [d] => 16 [h] => 20 [i] => 45 [s] => 0 [invert] => 0 [days] => 16 )
0 <= y שנים,
0 <= m חודשים,
16 <= d ימים,
20 <= h שעות,
45 <= i דקות,
0 <= s שניות.
days => כמות ימים מלאים כוללת (בלי חלוקה לחודשים). למשל עד ראש השנה נשאר 5 חודשים(m) ו-12 ימים(d) או 165 ימים(days) בלי חלוקה לחודשים.
invert => האם הפוך? אם ננסה לחסר מתאריך שכבר עבר את התאריך הנוכחי, הרי שהתוצאות יהיו שליליות. כדי שה-dateInterval לא יחזיק מספרים שליליים משאירים את המספרים כחיוביים, אך נרשם שהתאריכים נהפכו כדי לחסר מהגדול את הקטן. ערך זה יהיה או 1 (true, היה היפוך) או 0.
עד כאן זהו אם חיפשתם ללמוד איך לחסר תאריכים.
ישתמשו באובייקט dateinterval שנוצר עקב החיסור כדי לקבל את כל המידע.
חיבור תאריכים
חיבור שני תאריכים מתבצע גם הוא בעזרת מחלקת DateInterval. לא ניתן לחבר שני אובייקטים מסוג DateTime (וגם אין באמת צורך לחבר את היום ומחר כדי לגלות שאנחנו נהיה בשנת 4022). ניתן להוסיף לתאריך כלשהו עוד תווך זמן. (להוסיף להיום עוד חודש ולראות איזה תאריך יוצא.
כדי ליצור תווך זמן יש להשתמש בפורמט טיפה מוזר:
$interval = new DateInterval('P2Y4DT6H8M');
print_r($interval);
print_r($interval);
שני אותיות עיקריות מפרידות את המחרוזת לשני חלקים:
Period <- P מסמנת שכל מה שבא אחריה שייך לתווך תאריך
Time <- T מסמנת שכל מה שבא אחריה שייך לתווך זמן
שאר הסימנים מתחלקים בזוגות למספר ואות
2Y = 2 Years
4D = 4 Days
6H = 6 Hours
8M = 8 Minutes
נוצר אובייקט DateInterval עם הנתונים הבאים:
DateInterval Object ( [y] => 2 [m] => 0 [d] => 4 [h] => 6 [i] => 8 [s] => 0 [invert] => 0 [days] => )
עכשיו ניתן לחבר תאריך עם תווך הזה ונקבל תאריך שגדול בשנתיים, 4 ימים, 6 שעות ו8 דקות מהתאריך המקורי.
$now = new DateTime();
$interval = new DateInterval('P2Y4DT6H8M');
$now->add($interval);
echo $now->format('התאריך d/m/Y, השעה: H:i:s');
$interval = new DateInterval('P2Y4DT6H8M');
$now->add($interval);
echo $now->format('התאריך d/m/Y, השעה: H:i:s');
שימו לב לזכור להפריד ב-P ו-T את הימים-חודשים-שנים מה-שעות-דקות-שניות.
דרישה נוספת היא שהתקופות יופיעו מהגדולה לקטנה. כלומר קודם כמות השנים, אחריה חודשים, אחריה הימים, אחריהם השעות, דקות ולבסוף שניות ולא בסדר אחר.
לסיכום
ממבט ראשון יכול להראות מסובך, בעיקר אחרי החיבור תאריכים, אך בפועל חיסור תאריכים קל ופשוט בעזרת המחלקה הזו. היא תדאג בעצמה לחשב כמה חודשים ימים ושעות נשאר עד תאריך היעד בלי שתצטרכו לבצע את כל פעולות החשבון המעצבנות, לספור חודשים עם 30/31 יום בעצמכם ולוודא שדווקא בפברואר של השנה יש 29 יום.
חשוב מאוד: עד php 5.3.6 פונקציות אלו לא עבדו ב-windows
תגובות לכתבה:
וואו, תודה אחי!
חסכת לי המון עבודה של Javascript.
אם אתם עובדים עם wapm שכרגע גרסת הphp שלו היא 5.3.3
אתם חייבים לעדכן את הגרסה כמה שיותר מהר! בעזרת המדריך לעדכון גרסת php בwamp
http://phpguide.co.il/6_צעדים_קצרים_לעדכון_גרסת_php_ב_wamp.htm
לא יהיו לכם בעיות עם הפונקציות האלה באחסונים עם linux
שזה רוב האחסונים הקיימים ל php
mktime?
mktime מתאים לפעולות על התאריך הנוכחי.
יהיה קצת קשה לחסר יומיים מהראשון למרץ על ידי mktime שזה לא התאריך הנוכחי